home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / netconf / devices.c < prev    next >
C/C++ Source or Header  |  1996-08-03  |  9KB  |  403 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5. #include <limits.h>
  6. #include <netdb.h>
  7. #include <net/if.h>
  8. #include "netconf.h"
  9. #include "internal.h"
  10. #include "../misc/misc.h"
  11. #include "../xconf/xconf.h"
  12. #include "netconf.m"
  13.  
  14.  
  15. /* #Specification: devices / management
  16.     netconf knows how to load a devices module (probing) and how
  17.     to configure it (ifconfig). It also knows how to update the
  18.     different routes.
  19. */
  20. #
  21.  
  22. /*
  23.     Programme a network interface (ifconfig) only if needed,
  24.  
  25.     Compare the current configuration with the expected configuration.
  26.     If there is a mismatch (or the interface is not configure), then
  27.     it is reconfigure with the expected values.
  28.  
  29.     Return -1 if any error.
  30. */
  31. static int devices_ifconfig(
  32.     const char *device,
  33.     const char *expected_hst,
  34.     const char *expected_msk)
  35. {
  36.     IFCONFIG_INFO info;
  37.     int ret = ifconfig_getinfo (device,info);
  38.     if (ret == -1){
  39.         xconf_error (MSG_U(E_CANTPROBE
  40.             ,"Can't probe current setup of network device %s\n"
  41.              "No way to activate the network\n")
  42.             ,device);
  43.     }else{
  44.         DAEMON *dae = daemon_find ("ifconfig");
  45.         if (dae != NULL){
  46.             if (strcmp(info.ip_addr,expected_hst)==0
  47.                 && strcmp(info.netmask,expected_msk)==0
  48.                 && info.flags & IFF_UP){
  49.                 ret = 0;            
  50.             }else{
  51.                 char cmd[300];
  52.                 /* #Specification: netconf / ifconfig / down
  53.                     We always force an interface DOWN
  54.                     before reconfiguring it. It has
  55.                     the side effect of cleaning the route
  56.                     table for that device.
  57.                 */
  58.                 sprintf (cmd,"%s down",device);
  59.                 netconf_system_if ("ifconfig",cmd);
  60.                 sprintf (cmd,"%s %s netmask %s",device,expected_hst
  61.                     ,expected_msk);
  62.                 ret = netconf_system_if ("ifconfig",cmd);
  63.             }
  64.         }
  65.     }
  66.     return ret;
  67. }
  68. /*
  69.     Configure the loopback device.
  70.     Return -1 if any error.
  71. */
  72. int netconf_setloopback()
  73. {
  74.     /* #Specification: loopback / strategy
  75.         As far as I know, there is only a way to configure the
  76.         loopback device.
  77.  
  78.         /sbin/ifconfig lo 127.0.0.1
  79.         /sbin/route add -net loopback
  80.     */
  81.     int ret = devices_ifconfig ("lo","127.0.0.1","255.0.0.0");
  82.     if (ret == 0){
  83.         char gateway[PATH_MAX];
  84.         if (!route_isactive("127.0.0.0",gateway)){
  85.             ret = netconf_system_if ("route","add -net 127.0.0.0 lo");
  86.         }
  87.     }
  88.     return ret == 0 ? 0 : -1;
  89. }
  90. /*
  91.     Format in text the major IP number of a HOST
  92. */
  93. void devices_ip2a(struct hostent *ent, char *buf)
  94. {
  95.     unsigned char *numadr = (unsigned char *)ent->h_addr_list[0];
  96.     char *pt = buf;
  97.     int len = ent->h_length;
  98.     for (int i=0; i<len; i++){
  99.         pt += sprintf (pt,i==0 ? "%d":".%d",numadr[i]);
  100.     }
  101. }
  102. void devices_ip2a(struct hostent *ent, SSTRING &ip)
  103. {
  104.     char buf[16];
  105.     devices_ip2a (ent,buf);
  106.     ip.setfrom (buf);
  107. }
  108. /*
  109.     Format in text an IP number
  110. */
  111. void devices_ip2a(unsigned long ip, char *buf)
  112. {
  113.     union{
  114.         long num;
  115.         unsigned char car[4];
  116.     }u;
  117.     u.num = ip;
  118.     sprintf (buf,"%d.%d.%d.%d",u.car[3],u.car[2],u.car[1],u.car[0]);
  119. }
  120. /*
  121.     Format in text the major IP number of a NET
  122. */
  123. void devices_ip2a(struct netent *ent, char *buf)
  124. {
  125.     devices_ip2a (ent->n_net,buf);
  126. }
  127. void devices_ip2a(struct netent *ent, SSTRING &ip)
  128. {
  129.     char buf[16];
  130.     devices_ip2a (ent->n_net,buf);
  131.     ip.setfrom (buf);
  132. }
  133.  
  134. /*
  135.     Translate an IP number (ascii) into four number
  136.     Return -1 if the IP number is invalid.
  137. */
  138. int device_aip24 (const char *aip, int num4[4])
  139. {
  140.     int ret = 0;
  141.     for (int i=0; i<4; i++){
  142.         if (!isdigit(aip[0])){
  143.             ret = -1;
  144.             break;
  145.         }else{
  146.             int no = num4[i] = atoi(aip);
  147.             if (no < 0 || no > 255) ret = -1;
  148.             while (isdigit(*aip)) aip++;
  149.             if (i < 3 && *aip != '.'){
  150.                 ret = -1;
  151.                 break;
  152.             }
  153.             aip++;
  154.         }
  155.     }
  156.     return ret;
  157. }
  158.  
  159.  
  160. /*
  161.     Check is a string is valid IP number.
  162.     if (ishost), check if the IP is not a broadcast or a network address.
  163. */
  164. bool device_validip(const char *aip, bool ishost)
  165. {
  166.     int num4[4];
  167.     bool ret = false;
  168.     if (device_aip24(aip,num4) != -1){
  169.         ret = true;
  170.         if (ishost && (num4[3] == 0 || num4[3] == 255)){
  171.             ret = false;
  172.         }
  173.     }
  174.     return ret;
  175. }
  176. #if 0
  177. /*
  178.     Perform a gethostbyname with error reporting.
  179.     Return -1 if not found.
  180. */
  181. static int devices_gethostbyname(
  182.     const char *host,
  183.     const char *device,
  184.     char *ip_num,        // Will contain the formatted IP address
  185.     int  silent)        // Ok if not set, no error message
  186. {
  187.     struct hostent *ent = gethostbyname(host);
  188.     int ret = -1;
  189.     if (ent == NULL){
  190.         if (!silent){
  191.             xconf_error ("%s is not defined\n"
  192.                 "Can't configured device %s\n",host,device);
  193.         }
  194.     }else{
  195.         ret = 0;
  196.         devices_ip2a (ent,ip_num);
  197.     }
  198.     return ret;
  199. }
  200. /*
  201.     Perform a getnetbyname with error reporting.
  202.     Return -1 if not found.
  203. */
  204. static int devices_getnetbyname(
  205.     const char *net,
  206.     const char *device,
  207.     char *ip_num,        // Will contain the formatted IP address
  208.     int  silent)        // Ok if not set, no error message
  209. {
  210.     struct netent *ent = getnetbyname(net);
  211.     int ret = -1;
  212.     if (ent == NULL){
  213.         if (!silent){
  214.             xconf_error ("%s is not defined\n"
  215.                 "Can't configured device %s\n",net,device);
  216.         }
  217.     }else{
  218.         ret = 0;
  219.         devices_ip2a (ent,ip_num);
  220.     }
  221.     return ret;
  222. }
  223. #endif
  224. struct IFACE_NUMS{
  225.     char hst[20];
  226.     char net[20];
  227.     char msk[20];
  228. };
  229.  
  230. void device_setstdnetmask(
  231.     const char *hostip,    // IP number of a HOST
  232.     char *def_net,        // Default network number
  233.     char *def_msk)        // Default netmask
  234. {
  235.     int num4[4];
  236.     device_aip24 (hostip,num4);
  237.     if (num4[0] == 0){
  238.         strcpy (def_net,"0.0.0.0");
  239.         strcpy (def_msk,"0.0.0.0");
  240.     }else if (num4[0] <= 127){
  241.         sprintf (def_net,"%d.0.0.0",num4[0]);
  242.         strcpy (def_msk,"255.0.0.0");
  243.     }else if (num4[0] <= 191){
  244.         sprintf (def_net,"%d.%d.0.0"
  245.             ,num4[0],num4[1]);
  246.         strcpy (def_msk,"255.255.0.0");
  247.     }else{
  248.         sprintf (def_net,"%d.%d.%d.0"
  249.             ,num4[0],num4[1],num4[2]);
  250.         strcpy (def_msk,"255.255.255.0");
  251.     }
  252. }
  253.  
  254. static int device_copystr (char *dst, SSTRING &src)
  255. {
  256.     src.copy (dst);
  257.     return src.is_empty() ? -1 : 0;
  258. }
  259. /*
  260.     Get the IP number assigned to an interface (host,network and mask)
  261.     Fill default values if some information is not fully specified.
  262.     Return -1 if to much is missing.
  263. */
  264. static int device_ifaceinfo (
  265.     const char *device,        // Name of the device (for error report)
  266.     INTER_INFO &itf,
  267.     IFACE_NUMS &nums)
  268. {
  269.     int ret = -1;
  270.     int h_ok = device_copystr (nums.hst,itf.ipaddr);
  271.     int n_ok = device_copystr (nums.net,itf.network);
  272.     int m_ok = device_copystr (nums.msk,itf.netmask);
  273.     if (h_ok != -1){
  274.         /* #Specification: ifconfig / eth devices / 127.0.0.1
  275.             Linuxconf won't configure an ethernet
  276.             interface to 127.0.0.1. It will simply ignore it.
  277.  
  278.             This case happen when a properly configured
  279.             linux system without an ethernet adaptor get
  280.             one.
  281.         */
  282.         if (strcmp(nums.hst,"127.0.0.1")!=0){
  283.             /* #Specification: ifconfig / netmask and network / optionnal
  284.                 The netmask and network address of a network specification are
  285.                 optionnal. The kernel (or ifconfig or route, I don't know)
  286.                 compute suitable defaults.
  287.             */
  288.             char def_net[20];
  289.             char def_msk[20];
  290.             device_setstdnetmask(nums.hst,def_net,def_msk);
  291.             if (n_ok == -1) strcpy (nums.net,def_net);
  292.             if (m_ok == -1) strcpy (nums.msk,def_msk);
  293.             ret = 0;
  294.             if (!device_validip(nums.hst,true)
  295.                 || !device_validip(nums.net,false)
  296.                 || !device_validip(nums.msk,false)){
  297.                 ret = -1;
  298.                 xconf_error (
  299.                     "Invalid IP number for interface %s"
  300.                     ,device);
  301.             }
  302.         }
  303.     }
  304.     return ret;
  305. }
  306.  
  307. /*
  308.     Load a network device module.
  309.     Return -1 if any error
  310. */
  311. int device_insmod (const char *devname)
  312. {
  313.     return netconf_system_if ("modprobe",devname);
  314. }    
  315.  
  316.  
  317.     
  318.  
  319. /*
  320.     Initialise a network device and set the basic route to it.
  321. */
  322. static int device_set (
  323.     int dev_exist,        // Is the device configured in the kernel ?
  324.     const char *device,    // Name of the device
  325.     INTER_INFO &itf)
  326. {
  327.     int ret = -1;
  328.     IFACE_NUMS nums;
  329.     int ip_needed = device_ifaceinfo (device,itf,nums) != -1;
  330.     if (ip_needed){
  331.         /* #Specification: netconf / devices / modules
  332.             If a device (eth?) is not available in the kernel
  333.             linuxconf does a "modprobe device" to load the module.
  334.         */
  335.         if (!dev_exist)    dev_exist = device_insmod (device) != -1;
  336.         if (dev_exist){
  337.             if (ip_needed){
  338.                 ret = devices_ifconfig(device,nums.hst,nums.msk);
  339.                 if (ret == 0){
  340.                     char cmd[300];
  341.                     char gateway[PATH_MAX];
  342.                     int status = route_isactive(nums.net,gateway);
  343.                     if (status && strcmp(gateway,device)!=0){
  344.                         sprintf (cmd,"del -net %s",nums.net);
  345.                         ret = netconf_system_if ("route",cmd);
  346.                         status = 0;
  347.                     }
  348.                     if (!status){
  349.                         sprintf (cmd,"add -net %s %s",nums.net,device);
  350.                         ret = netconf_system_if ("route",cmd);
  351.                     }
  352.                 }
  353.             }
  354.         }else{
  355.             xconf_error (MSG_U(E_NODEVICE
  356.                 ,"Networking was configured\n"
  357.                  "for the interface %s\n"
  358.                  "but this device is not configured\n"
  359.                  "in the kernel\n")
  360.                 ,device);
  361.         }
  362.     }else if (!dev_exist){
  363.         // No configuration (IP or IPX) for this device
  364.         // but it is not there anyway
  365.         ret = 0;
  366.     }
  367.     return ret;
  368. }
  369. const char *tb_netdevices[]={
  370.     "eth0","eth1","eth2","eth3"
  371. };
  372. /*
  373.     Configure the main communication devices (ethernet) and set the
  374.     basic route.
  375.  
  376.     Return -1 if any error.
  377. */
  378. int netconf_setdevices()
  379. {
  380.     /* #Specification: network devices / lookup
  381.         netconf finds out which permanent network devices do exist
  382.         by reading /proc/net/dev. Slip devices are ignored because
  383.         they are not managed properply by netconf right now.
  384.  
  385.         In fact, netconf deal only with ETHx devices.
  386.     */
  387.     int    ret = 0;
  388.     HOSTINFO info;
  389.     if (netconf_loadinfos(info) != -1){
  390.         for (int i=0; i<NB_ETH; i++){
  391.             const char *devname = tb_netdevices[i];
  392.             ret |= device_set (devlist_devexist(devname)
  393.                 ,devname
  394.                 ,info.a[i]);
  395.         }
  396.     }
  397.     return ret;
  398. }
  399.  
  400.  
  401.  
  402.  
  403.